package org.example.category.service.impl;

import lombok.extern.slf4j.Slf4j;
import org.example.category.mapper.CategoryMapper;
import org.example.category.service.CategoryService;
import org.example.model.vo.h5.CategoryVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

@Service
@Slf4j
public class CategoryServiceImpl implements CategoryService {
    @Autowired
    private CategoryMapper categoryMapper;
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    private ConcurrentHashMap<String, AtomicLong> requestCountMap = new ConcurrentHashMap<>();
    private Lock lock = new ReentrantLock();

    @Override
//    @Cacheable(value = "category")
    public List<CategoryVo> selectAll() {
        List<CategoryVo> o = (List<CategoryVo>) redisTemplate.boundHashOps("category").get("categoryVoList");
        if (o != null) {
            return o;
        }

        // 防止缓存击穿
        String key = "category_request_lock";
        if (requestCountMap.containsKey(key)) {
            AtomicLong count = requestCountMap.get(key);
            count.incrementAndGet();
            if (count.get() > 100) {  // 限制并发请求数量，可根据实际情况调整
                try {
                    Thread.sleep(100);  // 等待一段时间再重试
                    return selectAll();
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        } else {
            requestCountMap.put(key, new AtomicLong(1));
        }

        try {
            lock.lock();
            List<CategoryVo> categoryVos = categoryMapper.selectAll(0L);
            categoryVos.forEach(categoryVo -> {
                List<CategoryVo> children = categoryMapper.selectAll(categoryVo.getId());
                categoryVo.setChildren(children);
            });

            // 为缓存设置随机过期时间
            int baseExpiration = 30 * 60;  // 30 分钟的基础过期时间（单位：秒）
            int randomOffset = ThreadLocalRandom.current().nextInt(-5 * 60, 5 * 60);  // 随机偏移 -5 到 5 分钟
            int expiration = baseExpiration + randomOffset;
            redisTemplate.expire("category", expiration, TimeUnit.SECONDS);

            log.info("categoryVoList: {}", categoryVos);
            redisTemplate.boundHashOps("category").put("categoryVoList", categoryVos);

            return categoryVos;
        } finally {
            lock.unlock();
            requestCountMap.remove(key);
        }
    }
}
